package com.ding.dailyup.service;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.StrUtil;
import com.ding.dailyup.entity.CollectStockEntity;
import com.ding.dailyup.entity.UserInfoEntity;
import com.ding.dailyup.exception.ParamException;
import com.ding.dailyup.exception.PointsException;
import com.ding.dailyup.model.UserBuyStrategy;
import com.ding.dailyup.model.UserCollectStock;
import com.ding.dailyup.model.UserInfo;
import com.ding.dailyup.repository.UserBuyStrategyRepositoy;
import com.ding.dailyup.repository.UserCollectStockRepository;
import com.ding.dailyup.repository.UserInfoRepository;
import com.ding.dailyup.exception.BOException;
import com.ding.dailyup.util.StockUtil;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
public class UserService {
	Logger logger = LoggerFactory.getLogger(UserService.class);
	@Autowired
	private WxMaService wxMaService;
	@Autowired
	private UserInfoRepository userRepository;
	@Autowired
	private UserCollectStockRepository userCollectStockRepository;
	@Autowired
	private UserBuyStrategyRepositoy userBuyStrategyRepositoy;
	@Autowired
	private RiskService riskService;

	@Transactional(rollbackFor = Exception.class)
	public UserInfo saveWxUser(String code, String ipAddr,
			UserInfoEntity userInfoEntity) {
		String sessionKey = "";
		String openId = "";
		try {
			WxMaJscode2SessionResult result = wxMaService.getUserService()
					.getSessionInfo(code);
			sessionKey = result.getSessionKey();
			openId = result.getOpenid();
		} catch (Exception e) {
			logger.error("获取open id 异常,code :{}, 异常:", code, e);
		}

		if (StrUtil.isEmpty(sessionKey) || StrUtil.isEmpty(openId)) {
			throw new BOException(String.format("微信open id 异常,code:%s", code));
		}
		Optional<UserInfo> userOptional = userRepository
				.findByWeixinOpenid(openId);

		String finalOpenId = openId;
		UserInfo user = userOptional.orElseGet(() -> {
			UserInfo user1 = new UserInfo();
			user1.setUsername(finalOpenId);
			user1.setPassword(finalOpenId);
			user1.setWeixinOpenid(finalOpenId);
			user1.setAvatar(userInfoEntity.getAvatarUrl());
			user1.setNickname(userInfoEntity.getNickName());
			user1.setGender(userInfoEntity.getGender());
			user1.setUserLevel(0);
			user1.setStatus(0);
			user1.setPoints(0L);
			return user1;
		});

		user.setLastLoginTime(LocalDateTime.now());
		user.setLastLoginIp(ipAddr);
		user.setSessionKey(sessionKey);
		return userRepository.save(user);
	}

	@Transactional(rollbackFor = Exception.class)
	public CollectStockEntity collectStock(Long userId, String stockCode) {
		int decrPoints = 0;
		long collectRecordId = 0L;
		UserInfo userInfo = userRepository.findUpdateById(userId)
				.orElse(new UserInfo());
		userCollectStockRepository.findByUserIdAndStatus(userId, 1)
				.ifPresent(userCollectStocks -> {
					if (userCollectStocks.size() >= 3) {
						throw new BOException("非会员用户最多收藏3只个股哦");
					}
				});
		Optional<UserCollectStock> optional = userCollectStockRepository
				.findByUserIdAndStockCodeAndStatus(userId, stockCode, 1);
		// 如果没有收藏过
		if (!optional.isPresent()) {
			UserCollectStock userCollectStock = new UserCollectStock();
			userCollectStock.setUserId(userId);
			userCollectStock.setStockCode(stockCode);
			// 获取收藏价格
			Pair<String, String> pair = StockUtil
					.getStockPriceWithSimpleCode(stockCode);
			userCollectStock.setCollectPrice(pair.getValue());
			userCollectStock.setStockName(pair.getKey());
			userCollectStockRepository.save(userCollectStock);
			collectRecordId = userCollectStock.getId();
			decrPoints = 5;
			// 收藏 且 扣除积分
			if (userInfo.getPoints() - decrPoints >= 0) {
				userInfo.setPoints(userInfo.getPoints() - decrPoints);
				userRepository.save(userInfo);
			} else {
				throw new PointsException("扣除5积分不足");
			}
		}else{
			collectRecordId = optional.get().getId();
		}
		CollectStockEntity collectStockEntity = new CollectStockEntity();
		collectStockEntity.setDecrPoints(decrPoints);
		collectStockEntity.setRecordId(collectRecordId);
		return collectStockEntity;
	}

	@Transactional(rollbackFor = Exception.class)
	public void cancelCollectStock(Long userId, String stockCode) {
		userCollectStockRepository
				.findByUserIdAndStockCodeAndStatus(userId, stockCode, 1)
				.ifPresent(userCollectStock -> {
					if (userCollectStock.getUserId().equals(userId)) {
						userCollectStock.setStatus(0);
						userCollectStockRepository.save(userCollectStock);
					}
				});
	}

	@Transactional(rollbackFor = Exception.class)
	// TODO 测试remark 风控
	public void remarkStock(Long userId, Long recordId, String remarkContext) {
		userCollectStockRepository.findById(recordId)
				.ifPresent(userCollectStock -> {
					if (userCollectStock.getUserId().equals(userId)) {
						if (!riskService.isRisky(remarkContext)) {
							userCollectStock.setRemark(remarkContext);
							userCollectStockRepository.save(userCollectStock);
						} else {
							throw new ParamException("备注信息不合法!");
						}
					}
				});
	}

	public List<UserCollectStock> listUserCollectStocks(Long userId) {
		return userCollectStockRepository.findByUserIdAndStatus(userId, 1)
				.orElse(Lists.newArrayList());
	}

	@Transactional(rollbackFor = Exception.class)
	public Integer dailyLoginReward(Long userId) {
		userRepository.findUpdateById(userId).ifPresent(user -> {
			user.setPoints(user.getPoints() + 10);
			userRepository.save(user);
		});
		return 10;
	}

	public List<UserBuyStrategy> getUserBuyStrategy(Long userId) {
		return userBuyStrategyRepositoy.findAllByUserIdAndStatus(userId, 1)
				.orElse(Lists.newArrayList());
	}
}
